#include "stdafx.h"
#include "Animation.h"
#include "common.h"
#include "ScriptSystem.h"
#include "TextureRender.h"
#include "Scene.h"
#include "texture.h"
#include "MapManager.h"

AnimInfoMap Animation::s_animinfo;

bool KeyFrameSet::Update( unsigned int delta )
{
    curframetime += delta;
    if( curframetime >= frames[current].frametime )
    {
        current += 1;
        current = curdir*framecount + (current%framecount);
        curframetime = 0;
        if( animmode == eAnim_Once && current == 0 )
            return false;
    }
    return true;
}

KeyFrameSet::~KeyFrameSet()
{
    SAFE_DELETE_ARRAY(frames);
}

Animation::Animation()
{
    m_anims = NULL;
    m_curanim = -1;   
    m_pRender = new CTextureRender;
    m_pRender->SetRenderType( eRender_Texture );
}

Animation::~Animation()
{
    SAFE_DELETE_ARRAY(m_anims);
    SAFE_DELETE(m_pRender);
}

bool Animation::Update( unsigned int delta )
{
    if( m_curanim >= 0 )
    {
        bool result = m_anims[m_curanim].Update(delta);
        if(!result)
            m_curanim = -1;
    }
    return true;
}

bool Animation::StartAnim( int anim , EAnimDirection dir)
{
    if( anim < 0 || (unsigned int)anim >= m_animcount )
        return false;
    if( m_curanim >= 0 )
        m_anims[m_curanim].Stop();
    m_curanim = anim;
    m_anims[m_curanim].Start(dir);
    return true;
}

bool Animation::StartAnim( LPTSTR name , EAnimDirection dir /*= (EAnimDirection)0 */ )
{
    for( unsigned int i = 0; i < m_animcount; i++ )
    {
        if( _tcscmp(name, m_anims[i].name) == 0 )
            return StartAnim(i, dir);
    }
    return StartAnim(0, dir);
}

void Animation::Render( int x, int y, int sizex, int sizey, int layer )
{
    if( m_curanim >= 0 )
    {
        KeyFrameSet &cur = m_anims[m_curanim];
        KeyFrame &frame = cur.frames[cur.current];
        
        TextureInfo *texinfo = CD3DManager::Instance().GetTextureInfo( cur.texid );
        CHECK_PTR_VOID( texinfo );
        if( sizex == -1 )
        {
            sizex = int(texinfo->width * ( frame.u2 - frame.u1 ));
            IRect r(0,0,sizex,0);
            CMapManager::Instance().ConvertToScaledCoord(r);
            sizex = r.Width()/4;
        }
        if( sizey == -1 )
        {
            sizey = int(texinfo->height * ( frame.v2 - frame.v1 ));
            IRect r(0,0,sizey,0);
            CMapManager::Instance().ConvertToScaledCoord(r);
            sizey = r.Width()/4;
        }
        //float minx = (float)x;
        //float miny = (float)y;
        //Vertex_RHW_TEX ver[]=
        //{
        //    {minx,miny,0.0f,1.0f,m_u1,m_v1,m_u1_2,m_v1_2},
        //    {maxx,miny,0.0f,1.0f,m_u2,m_v1,m_u2_2,m_v1_2},
        //    {maxx,maxy,0.0f,1.0f,m_u2,m_v2,m_u2_2,m_v2_2},

        //    {minx,miny,0.0f,1.0f,m_u1,m_v1,m_u1_2,m_v1_2},
        //    {maxx,maxy,0.0f,1.0f,m_u2,m_v2,m_u2_2,m_v2_2},
        //    {minx,maxy,0.0f,1.0f,m_u1,m_v2,m_u1_2,m_v2_2},
        //};
        //tbase.AddVertexData( ver, 6 );

        m_pRender->SetUV( frame.u1, frame.v1, frame.u2, frame.v2 );
        m_pRender->SetTextureID( cur.texid );
        m_pRender->SetPriority( layer );
        m_pRender->SetPosition( x, y );
        m_pRender->SetSize( sizex, sizey );

        CScene::Instance().AddRenderObject( m_pRender );
       // m_texture.Render( x,y,sizex,sizey, frame.u1,frame.v1,frame.u2,frame.v2);
        //CD3DManager::Instance().DrawTexture( cur.texid, x, y, sizex, sizey, frame.u1, frame.v1, frame.u2, frame.v2 );
    }
}

void Animation::Render( int x, int y, int layer )
{
	Render( x, y, -1, -1,layer );
}

bool Animation::Initialize( LPTSTR name )
{
    AnimInfoMap::iterator iter = s_animinfo.find(name);
    if( iter == s_animinfo.end() )
        return false;
    AnimationInfo &info = iter->second;
    unsigned int animcount = info.AnimList.size();
    m_animcount = animcount;
    m_anims = new KeyFrameSet[animcount];
    for( unsigned int i=0; i<animcount; i++ )
    {
        KeyFrameSet &p = m_anims[i];
        KeyFrameSetInfo &kfsInfo = info.AnimList[i];
        float vinterval = ( kfsInfo.endv - kfsInfo.startv )/(float)kfsInfo.direction;
        p.animmode = kfsInfo.animmode;
        p.curframetime = 0;
        p.current = 0;
        p.direction = kfsInfo.direction;
        p.framecount = kfsInfo.framecount;
        p.curframetime = 0;
        p.curdir = 0;
        _tcscpy( p.name, kfsInfo.animname );
        float hinterval = 1.0f/kfsInfo.framecount;
        unsigned int keyframecount = kfsInfo.framecount*kfsInfo.direction;
        p.frames = new KeyFrame[keyframecount];
        for( unsigned int j=0; j<kfsInfo.direction; j++ )
        {
            for( unsigned int k=0; k<kfsInfo.framecount; k++ )
            {
                unsigned int index = j*kfsInfo.framecount + k;
                p.frames[index].frametime = kfsInfo.frametime;
                p.frames[index].u1 = k*hinterval;
                p.frames[index].v1 = j*vinterval;
                p.frames[index].u2 = (k+1)*hinterval;
                p.frames[index].v2 = (j+1)*vinterval;
            }
        }
        p.texid = CD3DManager::Instance().AddTexture(kfsInfo.texture, kfsInfo.colorkey);
    }
    return true;
}

void AddAnimInfo( AnimationInfo &info )
{
    Animation::s_animinfo[info.name] = info;
    return;
}